<?php
declare (strict_types=1);

namespace app\common\library\wechat;

use app\common\enum\Client as ClientEnum;
use app\common\library\helper;
use app\common\model\OrderSub as OrderSubModel;
use app\common\model\UserOauth as UserOauthModel;
use app\store\model\Express as ExpressModel;
use cores\exception\BaseException;


/**
 * 微信小程序用户管理类
 * Class WxUser
 * @package app\common\library\wechat
 */
class WxSendGood extends WxBase
{
    // 微信支付配置
    private $config;

    // 当前商城ID
    private $storeId;

    // 物流配送
    const DELIVERY_EXPRESS = 1;

    // 虚拟商品
    const DELIVERY_VIRTUAL = 3;

    /**
     * 构造函数
     * @param array $config
     * @param int|null $storeId
     */
    public function __construct(array $config = [], ?int $storeId = null)
    {
        parent::__construct();
        $this->config  = $config;
        $this->storeId = $storeId;
        if (!empty($this->config)) {
            $this->setConfig($this->config['app_id'], $this->config['app_secret']);
        }
    }
    //微信物流发货
    /*public function sendWechatOrder($order){
        $order_sub = OrderSubModel::getOrderSubBy($order['order_parent_id']);
        if($order_sub['pay_money'] == '0.00'){//微信支付金额为0时，不去微信发货
            return false;
        }
        $token = $this->getAccessToken();
        if (!$token) {
            throwError('微信配置有误');
        }

        //获取用户openid
        if($order['user_id']){
            $userInfo = UserOauthModel::getOauth($order['user_id'],'MP-WEIXIN');
        }

        //获取快递公司
        if($order['express_id']){
            $model = new ExpressModel;
            $express = $model->detail($order['express_id']);
        }
        $transaction_id = $order['transaction_id']??'';
        $title = $order['title']??'';
        $openid = $userInfo['oauth_id']??'';
        $mobile = $order['mobile']??'';
        $tracking_no = $order['express_no']??'';
        $express_company = $express['kuaidi100_code']??'';
        $url = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token={$token}";
        $upload_time = date('Y-m-d\TH:i:s.vP');
        $arrayData = [
            "order_key" => [
                "order_number_type" => 2,
                "transaction_id" => $transaction_id
            ],
            "delivery_mode" => 1,
            "logistics_type" => 1,
            "shipping_list" => [
                [
                    "item_desc" => $title,
                    "contact" => [
                        "receiver_contact" => substr_replace($mobile, '****', 3, 4)
                    ],
                    "tracking_no" => $tracking_no,
                    "express_company" => $express_company,
                ]
            ],
            "upload_time" => $upload_time,
            "payer" => [
                "openid" => $openid
            ]
        ];
        $result = helper::httpRequest($url, json_encode($arrayData,JSON_UNESCAPED_UNICODE));
        log_record([
            'name' => '后台发货同步到微信物流发货',
            'openid' => $openid,
            'appId' => $this->appId,
            'order_id' => $order['order_id'],
            'result' => $result
        ]);
        return json_decode($result, true);
    }*/
    //获取发货订单信息
    public function getWxSendOrderStatus($transaction_id)
    {
        $token  = $this->getAccessToken();
        $url    = "https://api.weixin.qq.com/wxa/sec/order/get_order?access_token=" . $token;
        $data   = [
            'transaction_id' => $transaction_id
        ];
        $data   = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        $result = helper::httpRequest($url, $data);
        $result = json_decode($result, true);
        return $result;

    }

    //微信虚拟商品发货（虚拟商品）
    public function sendWechatOrderSelfPickup($order)
    {
        $order_sub = OrderSubModel::getOrderSubBy($order['order_id']);
        if ($order_sub['pay_money'] == '0.00') {//微信支付金额为0时，不去微信发货
            return false;
        }
        $token = $this->getAccessToken();
        if (!$token) {
            throwError('微信配置有误');
        }

        //获取用户openid
        if ($order['user_id']) {
            $userInfo = UserOauthModel::getOauth($order['user_id'], 'MP-WEIXIN');
        }

        $transaction_id = $order['transaction_id'] ?? '';
        if (empty($transaction_id)) {
            return false;
        }
        $title       = $order['title'] ?? '';
        $openid      = $userInfo['oauth_id'] ?? '';
        $url         = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token={$token}";
        $upload_time = date('Y-m-d\TH:i:s.vP');
        $arrayData   = [
            "order_key"      => [
                "order_number_type" => 2,
                "transaction_id"    => $transaction_id
            ],
            "delivery_mode"  => 1,
            "logistics_type" => 3,
            "shipping_list"  => [
                [
                    "item_desc" => $title
                ]
            ],
            "upload_time"    => $upload_time,
            "payer"          => [
                "openid" => $openid
            ]
        ];
        $result      = helper::httpRequest($url, json_encode($arrayData, JSON_UNESCAPED_UNICODE));
        log_record([
            'name'     => '后台发货同步到微信物流发货/虚拟自提',
            'openid'   => $openid,
            'appId'    => $this->appId,
            'order_id' => $order['order_id'],
            'result'   => $result
        ]);
        return json_decode($result, true);
    }


    /**
     * 发货信息同步微信平台
     * @param mixed $completed 订单详情
     * @param array $param 发货信息参数
     * @return bool
     * @throws BaseException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function syncMpWeixinShipping($completed, array $param): bool
    {
        // 构建发货信息参数
        $param = $this->buildParam($completed, $param);
        // 仅微信小程序端并且使用微信支付的订单才可以同步
        if (!$param['syncMpWeixinShipping']) {
            return false;
        }
        // 请求微信API接口
        $response = $this->uploadShippingInfo($this->buildApiParam($completed, $param));
        if ($response['errcode'] == 0 || $response['errcode'] == 10060001) {
            return true;
        } else {
            throwError('同步微信发货失败,' . $response['errmsg']);
            exit;
        }
    }

    /**
     * 构建发货信息参数
     * @param $completed
     * @param array $param
     * @return array
     */
    private function buildParam($completed, array $param): array
    {
        // 设置默认的参数
        $param = helper::setQueryDefaultValue($param, [
            // 同步至微信小程序《发货信息录入》
            'syncMpWeixinShipping' => 1,
            // 物流模式：1物流配送 3虚拟商品 4用户自提
            'logisticsType'        => self::DELIVERY_EXPRESS,
            // 物流公司ID
            'expressId'            => '',
            // 物流单号
            'expressNo'            => '',
        ]);
        return $param;
    }

    /**
     * 构建API参数
     * @param $completed
     * @param array $param
     * @return array
     * @throws BaseException
     */
    private function buildApiParam($completed, array $param): array
    {
        // 获取物流公司编码
        $param['expressId'] > 0 && $expressCode = $this->getExpressCode($param['expressId']);
        return [
            'order_key'        => [
                // 订单单号类型：1使用下单商户号和商户侧单号 2使用微信支付单号
                'order_number_type' => 2,
                // 支付交易对应的微信订单号
                'transaction_id'    => $completed['transaction_id'],
            ],
            // 物流模式：1物流配送 3虚拟商品 4用户自提
            'logistics_type'   => $param['logisticsType'],
            // 发货模式：1、UNIFIED_DELIVERY（统一发货）2、SPLIT_DELIVERY（分拆发货）
            'delivery_mode'    => 1,
            // 用于标识分拆发货模式下是否已全部发货完成 示例值: true/false
            'is_all_delivered' => true,
            'shipping_list'    => [
                [
                    'express_company' => $expressCode ?? '',                // 物流公司编码
                    'tracking_no'     => $param['expressNo'],                   // 物流单号
                    'item_desc'       => implode(',', array_column($completed['goods']->toArray(), 'goods_name')),    // 商品信息
                ]
            ],
            // 上传时间 (RFC3339格式)
            'upload_time'      => \date(DATE_RFC3339),
            // 微信用户openid
            'payer'            => ['openid' => $this->getUserOpenId($completed['user_id'])],
        ];
    }

    /**
     * 获取物流公司编码 [这里用快递鸟编码格式]
     * @param int $expressId
     * @return mixed
     * @throws BaseException
     */
    private function getExpressCode(int $expressId)
    {
        $detail = \app\common\model\Express::detail($expressId);
        empty($detail) && throwError('很抱歉，未找到指定的物流公司');
        return $detail['kuaidi100_code'];
    }

    /**
     * 发货信息录入接口
     * api文档: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html
     * @throws BaseException
     */
    public function uploadShippingInfo(array $params)
    {
        // 微信接口url
        $accessToken = $this->getAccessToken();
        $apiUrl      = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token={$accessToken}";
        // 执行请求
        $result = $this->post($apiUrl, $this->jsonEncode($params));
        // 记录日志
        log_record(['name' => '微信小程序-发货信息录入接口', 'url' => $apiUrl, 'params' => $params, 'result' => $result]);
        // 返回结果
        $response = $this->jsonDecode($result);
        if (!isset($response['errcode'])) {
            throwError('微信API请求失败：not found errcode');
            return false;
        }
        if ($response['errcode'] != 0) {
            throwError('微信API请求失败：not found errcode' . $response['errmsg']);;
            return false;
        }
        return $response;
    }

    /**
     * 获取微信小程序用户openid
     * @param int $userId
     * @return mixed
     * @throws BaseException
     */
    private function getUserOpenId(int $userId)
    {
        $openid = UserOauthModel::getOauthIdByUserId($userId, ClientEnum::MP_WEIXIN);
        empty($openid) && throwError('很抱歉，未找到当前用户的openid');
        return $openid;
    }

}